package cn.com.callback

import cn.com.kh.KHDBConfig
import cn.com.kh.KHUtil
import cn.com.elite.EliteBean;
import cn.com.elite.Util;
import net.sf.json.JSONObject
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.jdbc.core.JdbcTemplate

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
 *
 * @Title: 项目Token相关统一管理接口* @author: LJT*
 *
 */

public class apiGetToken implements ServiceBackInvoke {
    private static final Log log = LogFactory.getLog(apiGetToken.class);

    public String doCallBack(EliteBean eliteBean, HttpServletRequest request, HttpServletResponse response) {

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");

        JSONObject result = new JSONObject();
        JSONObject datatoken = new JSONObject();
        String access_token = "";

        // 调用IP过滤
        if (KHDBConfig.getParam(eliteBean, "#APIIP") == "1" && !KHUtil.getRemoteHost(request)) {
            log.warn("API被非法IP调用-Request Not Allow!");
            return "Request Not Allow!";
        }

        // 调用类型校验,此接口仅支持GET
        String getMethod = request.getMethod();
        log.debug("getMethod:" + getMethod);
        if (!getMethod.equals("GET")) {
            log.error("HTTP请求调用类型错误，接口调用失败：" + getMethod);
            result.put("code", -1);
            result.put("message", "HTTP请求调用类型错误，接口调用失败：" + getMethod);
            return result;
        }

        // 获取所有Header
        Map<String, String> mapHeader = new HashMap<String, String>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            log.debug("Call Header-" + key + ":" + value);

            mapHeader.put(key, value);
        }

        // 获取所有参数名
        Map<String, String> mapParams = new HashMap<String, String>();
        Enumeration ep = request.getParameterNames();
        while (ep.hasMoreElements()) {
            String key = (String) ep.nextElement();
            String value = request.getParameter(key);
            log.debug("Call Parameter-" + key + ":" + value);

            mapParams.put(key, value);
        }

        // 获取调用数据
        String Syncpram = request.getQueryString();
        log.info("接收调用GET参数信息：" + Syncpram);

        // 获取数据源List<Map<String, Object>>
        JdbcTemplate jt = new JdbcTemplate(eliteBean.getDataSource());

        String app_ID = request.getParameter("appid");
        String force_Refresh = request.getParameter("force_refresh");
        String return_Char = request.getParameter("return_char");

        //  入参为空
        if (KHUtil.isNull(app_ID)) {
            log.debug("appid 入参为空-无法完成操作!");
            result.put("code", -2);
            result.put("message", "appid 入参为空-无法完成操作!");

            return result;
        }

        try {
            app_ID = app_ID.toUpperCase();
            // 判断是否强制刷新
            if (force_Refresh == "true") {
                // 强制刷新
                log.warn("调用方要求强制刷新Token:" + force_Refresh);
                String dealSQL = "Update KH_Accesstoken Set Del_Flag = 1 Where Del_Flag = 0 And APP_ID = ?";
                int dealNum = jt.update(dealSQL, app_ID);
                log.warn("调用方要求强制刷新Token结果:" + dealNum);
            }

            // 检查当前Token状态
            String selectSQL = "Select Token, Expired - Timestampdiff(Second, Createdtime, Now()) As Expired From Kh_Accesstoken Where App_Id = ? And Del_Flag = 0 And Date_Add(Createdtime, Interval Expired Second) > Now() Order By Createdtime Desc Limit 1";
            List<Map<String, Object>> selectExits = jt.queryForList(selectSQL, app_ID);
            if (selectExits.size() > 0) {
                Map selectExitsm = selectExits.get(0);
                access_token = selectExitsm.get("Token");
                Long EXPIRED = Long.parseLong(selectExitsm.get("Expired").toString());

                result.put("code", 1);
                result.put("message", "查询完成");
                datatoken.put("access_token", access_token);
                datatoken.put("expires_in", EXPIRED);
                result.put("value", datatoken);

            } else {
                Map<String, String> tokenMap = new HashMap<>();
                /*
                WX开头 微信小程序&公众号
                QW开头 企业微信
                */
                if (app_ID.startsWith("QW")) {
                    tokenMap = getQWToken(eliteBean, app_ID);
                } else if (app_ID.startsWith("WX")) {
                    tokenMap = getWXToken(eliteBean, app_ID, force_Refresh);
                } else {
                    log.warn("获取Token类型不支持");
                    result.put("code", -2);
                    result.put("message", "获取Token类型不支持");
                    result.put("value", datatoken);
                    return result.toString();
                }

                access_token = tokenMap.get("access_token");
                Long EXPIRED = Long.parseLong(tokenMap.get("expires_in").toString());

                dealToDB(jt, app_ID, access_token, EXPIRED);

                result.put("code", 1);
                result.put("message", "更新完成");
                datatoken.put("access_token", access_token);
                datatoken.put("expires_in", EXPIRED);
                result.put("value", datatoken);

            }

        } catch (Exception e) {
            log.error("接口处理异常", e);
            // 失败返回

            result.put("code", -1);
            result.put("message", e.getMessage());
            result.put("value", datatoken);
            return result.toString();

        }

        log.debug("Token处理完成返回结果:" + result.toString());

        return return_Char == "true" ? access_token : result.toString();
    }

    // 将Token更新到DB
    public static void dealToDB(JdbcTemplate jt, String APP_ID, String access_token, Long expires_in) {

        // 清理超长时间的Token
        String dealSQL = "Delete From KH_Accesstoken Where Createdtime < Date_Add(Now(), Interval - 1 Day) And APP_ID = ?";
        jt.update(dealSQL, APP_ID);

        // 标识近期内Token无效
        dealSQL = "Update KH_Accesstoken Set Del_Flag = 1 Where Del_Flag = 0 And APP_ID = ?";
        jt.update(dealSQL, APP_ID);

        // 将新获取的Token入库存储
        dealSQL = "Insert Into Kh_Accesstoken (Rec_Id, Token, Createdtime, Expired, Del_Flag, APP_ID) Values (UUID(), ?, Now(), ?, 0, ?)";
        jt.update(dealSQL, access_token, expires_in, APP_ID);
    }

    // 获取微信小程序&公众号Token
    public static Map<String, String> getWXToken(EliteBean eliteBean, String opsource, String force_Refresh) {

        Map<String, String> tokenMap = new HashMap<String, String>();

        // 调用凭据配置信息
        String APPID = KHDBConfig.getParamConfig(eliteBean, opsource + "-appID");
        String APPSECRET = KHDBConfig.getParamConfig(eliteBean, opsource + "-appSecret");
        log.debug("获取WX稳定版接口调用凭据 配置信息【APPID】：" + APPID + "【APPSECRET】：" + APPSECRET);

        // 调用微信获取最新Token
        String wxTokenURL = "https://api.weixin.qq.com/cgi-bin/stable_token";
        log.debug("获取WX稳定版接口调用凭据 URL:" + wxTokenURL);

        // 调用报文
        JSONObject wxTokenJson = new JSONObject();
        wxTokenJson.put("grant_type", "client_credential");
        wxTokenJson.put("force_refresh", KHUtil.isNull(force_Refresh) ? false : force_Refresh == "true");
        wxTokenJson.put("appid", APPID);
        wxTokenJson.put("secret", APPSECRET);
        log.debug("获取WX稳定版接口调用凭据 报文:" + wxTokenJson);

        String wxTokenResult = Util.doHttpPost(wxTokenURL, wxTokenJson.toString(), "UTF-8", 5000, 0);
        log.debug("获取WX稳定版接口调用凭据 返回：" + wxTokenResult);
        JSONObject wxTokenResultJson = JSONObject.fromObject(wxTokenResult);

        if (wxTokenResultJson.has("access_token")) {
            try {
                // 解析返回 Token
                String access_token = wxTokenResultJson.getString("access_token");
                String expires_in = wxTokenResultJson.getString("expires_in");
                tokenMap.put("access_token", access_token);
                tokenMap.put("expires_in", expires_in);

            } catch (Exception e) {
                log.error("获取WX稳定版接口调用凭据 异常", e);
            }
        } else {
            log.warn("获取WX稳定版接口调用凭据 返回数据解析错误");
        }

        return tokenMap;
    }

    // 获取企业微信API调用凭据
    public static Map<String, String> getQWToken(EliteBean eliteBean, String opsource) {

        Map<String, String> tokenMap = new HashMap<String, String>();

        // 调用凭据配置信息
        String APPID = KHDBConfig.getParamConfig(eliteBean, opsource + "-appID");
        String APPSECRET = KHDBConfig.getParamConfig(eliteBean, opsource + "-appSecret");
        log.debug("获取企业微信API调用凭据 配置信息【APPID】：" + APPID + "【APPSECRET】：" + APPSECRET);

        // 获取企业微信API调用凭据
        String wxTokenURL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + APPID + "&corpsecret=" + APPSECRET;
        log.debug("获取企业微信API调用凭据 TokenURL:" + wxTokenURL);

        String wxTokenResult = Util.doHttpGet(wxTokenURL, "UTF-8", 5000, 0);
        log.debug("获取企业微信API调用凭据 Token返回：" + wxTokenResult);
        JSONObject wxTokenJson = JSONObject.fromObject(wxTokenResult);

        if (wxTokenJson.has("access_token")) {
            try {

                String access_token = wxTokenJson.getString("access_token");
                String expires_in = wxTokenJson.getString("expires_in");
                tokenMap.put("access_token", access_token);
                tokenMap.put("expires_in", expires_in);

            } catch (Exception e) {
                log.error("获取企业微信API调用凭据 异常", e);
            }
        } else {
            log.warn("获取企业微信API调用凭据 返回数据解析错误");
        }

        return tokenMap;
    }

}